#ifndef MML_H
#define MML_H

namespace Cvekas {

/// Node in MML tree
class MMLNode
{
public:
	/// Constructor
	MMLNode(const std::string& name, const std::string& value = "");
	/// Copy constructor
	MMLNode(const MMLNode& node);

	/// Returns child first child with provided name. Throws if no such child.
	MMLNode& getChild(const std::string& name);
	/// Removes first child with provided name. Throws if no such child.
	void removeChild(const std::string& name);
	/// Inserts new node after child with provided name. Throws if no such child.
	void insertAfter(const std::string& name, const MMLNode& node);
	/// Appends new node to the end of children list
	void append(const MMLNode& node);

	/// List of childrens of this node
	std::list<MMLNode> children;	
	
	/// Node name
	std::string name;
	/// Node value
	std::string value;

private:
	std::list<MMLNode>::iterator find(const std::string& name);
};

/// \brief Minimalistic markup language
///
/// Meta-language for data description, heavily inspired by lisp and (flaws of) XML. \n\n
/// Grammar in BNF: \n
/// <tt>
/// node ::= "(" \<literal\> \<literal\> <nodelist\> ")" \n
/// nodelist ::= \<nothing\> | \<node\> \<nodelist\>
/// </tt>
class MML
{
public:
	/// Constructor
	MML();

	/// Constructor. Parses given string to a MMLNode tree.
	MML(const std::string& input);

	/// Serializes MMLNode tree to a string
	std::string serialize();

	/// Returns root MMLNode
	MMLNode& getRoot();

private:
	class MMLToken
	{
	public:
		enum Type
		{
			MML_BRACE_OPEN,
			MML_BRACE_CLOSE,
			MML_LITERAL
		};

		MMLToken(Type type, const std::string& literal = std::string())
		: type(type), literal(literal) 
		{}

		Type type;
		std::string literal;
	};

	void tokenize(const std::string& input, std::vector<MMLToken>& tokens);
	MMLNode parse(const std::vector<MMLToken>& tokens);
	MMLNode _parse(const std::vector<MMLToken>& tokens, size_t start, size_t end);

	std::string _serialize(const MMLNode& node, const std::string& prefix = "");

	MMLNode root;		
};

} // namespace

#endif

